import React, { useState, useRef, useCallback, useMemo } from 'react';
import './index.css';

interface VirtualListProps {
  data: any[];
  getItemHeight: (item: any, index: number) => number; // 动态高度函数
  containerHeight: number;
  renderItem: (item: any, index: number) => React.ReactNode;
  overscan?: number; // 预加载项目数量，默认为2
  // 无限滚动相关
  loadMore?: () => void; // 加载更多函数
  hasMore?: boolean; // 是否还有更多数据
  threshold?: number; // 触发距离，默认100px
}

const VirtualList: React.FC<VirtualListProps> = ({
  // 传递过来 的数据
  data,
  // 获取项目高度
  getItemHeight,
  // 容器高度
  containerHeight,
  // 渲染项目
  renderItem,
  // 预加载项目数量，默认为2
  overscan = 2, //
  // 加载更多函数
  loadMore,
  // 是否还有更多数据
  hasMore = true,
  // 默认距离底部50px触发
  threshold = 50, 
}) => {
  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef<HTMLDivElement>(null);
  const loadMoreTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // 计算每个项目的累积高度
  const itemPositions = useMemo(() => {
    const positions: number[] = [0];
    let totalHeight = 0;
    
    for (let i = 0; i < data.length; i++) {
      totalHeight += getItemHeight(data[i], i);
      positions.push(totalHeight);
    }
    
    return positions;
  }, [data, getItemHeight]);

  // 计算总高度
  const totalHeight = itemPositions[data.length] || 0;
  
  // 计算可见区域的起始和结束索引（包含预加载）
  const startIndex = useMemo(() => {
    let index = 0;
    while (index < data.length && itemPositions[index + 1] <= scrollTop) {
      index++;
    }
    // 添加预加载：向上扩展 overscan 个项目
    return Math.max(0, index - overscan);
  }, [scrollTop, itemPositions, data.length, overscan]);

  const endIndex = useMemo(() => {
    let index = startIndex;
    while (index < data.length && itemPositions[index] < scrollTop + containerHeight) {
      index++;
    }
    // 添加预加载：向下扩展 overscan 个项目
    return Math.min(data.length, index + overscan);
  }, [startIndex, scrollTop, containerHeight, itemPositions, data.length, overscan]);

  // 处理滚动事件
  const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
    const scrollTop = e.currentTarget.scrollTop;
    setScrollTop(scrollTop);
    
    // 无限滚动逻辑：检测是否滚动到底部附近
    if (loadMore && hasMore) {
      // 滚动高度
      const scrollHeight = e.currentTarget.scrollHeight;
      // 视口高度
      const clientHeight = e.currentTarget.clientHeight;
      
      // 当滚动到距离底部 threshold 像素时触发加载更多
      if (scrollTop + clientHeight >= scrollHeight - threshold) {
        // 防抖：清除之前的定时器
        if (loadMoreTimeoutRef.current) {
          clearTimeout(loadMoreTimeoutRef.current);
        }
        
        // 延迟100ms执行，避免快速连续触发
        loadMoreTimeoutRef.current = setTimeout(() => {
          loadMore();
        }, 100);
      }
    }
  }, [loadMore, hasMore, threshold]);

  // 只渲染可见的元素
  const visibleItems = useMemo(() => {
    return data.slice(startIndex, endIndex).map((item, index) => {
      const actualIndex = startIndex + index;
      const top = itemPositions[actualIndex];
      const height = getItemHeight(item, actualIndex);
      
      return (
        <div
          key={actualIndex}
          style={{
            position: 'absolute',
            top,
            height,
            width: '100%'
          }}
        >
          {renderItem(item, actualIndex)}
        </div>
      );
    });
  }, [data, startIndex, endIndex, itemPositions, getItemHeight, renderItem]);

  return (
    <div
      ref={containerRef}
      style={{
        height: containerHeight,
        overflow: 'auto',
        position: 'relative'
      }}
      onScroll={handleScroll}
    >
      <div style={{ height: totalHeight, position: 'relative' }}>
        {visibleItems}
      </div>
    </div>
  );
};

export default VirtualList;
